package middleware

import (
	"github.com/danfwing/sd-project/pkg/utils"
	"github.com/gin-gonic/gin"
	"log/slog"
	"net/http"
	"strings"
	"sync"
)

// AuthMiddleware 验证 Bearer JWT token 的中间件
// 1 debug 2 test 3 product

// WhiteListConfig 白名单配置结构
type WhiteListConfig struct {
	paths map[string]bool
	mu    sync.RWMutex
}

// NewWhiteListConfig 创建新的白名单配置
func NewWhiteListConfig() *WhiteListConfig {
	return &WhiteListConfig{
		paths: make(map[string]bool),
	}
}

// Add 添加白名单路径
func (w *WhiteListConfig) Add(paths ...string) {
	w.mu.Lock()
	defer w.mu.Unlock()
	for _, path := range paths {
		w.paths[path] = true
	}
}

// Remove 移除白名单路径
func (w *WhiteListConfig) Remove(paths ...string) {
	w.mu.Lock()
	defer w.mu.Unlock()
	for _, path := range paths {
		delete(w.paths, path)
	}
}

// Clear 清空白名单
func (w *WhiteListConfig) Clear() {
	w.mu.Lock()
	defer w.mu.Unlock()
	w.paths = make(map[string]bool)
}

// Contains 检查路径是否在白名单中
func (w *WhiteListConfig) Contains(path string) bool {
	w.mu.RLock()
	defer w.mu.RUnlock()

	// 直接匹配
	if w.paths[path] {
		return true
	}

	// 通配符匹配
	for whitePath := range w.paths {
		if strings.HasSuffix(whitePath, "/*") {
			prefix := strings.TrimSuffix(whitePath, "/*")
			if strings.HasPrefix(path, prefix) {
				return true
			}
		}
	}

	return false
}

func AuthMiddleware(mode int, whiteList *WhiteListConfig) gin.HandlerFunc {
	return func(c *gin.Context) {

		// 检查是否是白名单路径
		if whiteList != nil && whiteList.Contains(c.Request.URL.Path) {
			c.Next()
			return
		}

		//debug
		if mode == 1 || mode == 2 {
			c.Set("userCode", "admin-test")
			c.Set("username", "admin-test")
			c.Set("roles", []string{"admin"})
			c.Next()
			return
		}

		// 从 Authorization header 中获取 access token
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			c.JSON(http.StatusUnauthorized, gin.H{
				"code": 401,
				"msg":  "Authorization header is required",
			})
			c.Abort()
			return
		}

		// 检查 Authorization header 格式
		parts := strings.SplitN(authHeader, " ", 2)
		if !(len(parts) == 2 && parts[0] == "Bearer") {
			c.JSON(http.StatusUnauthorized, gin.H{
				"code": 401,
				"msg":  "Authorization header format must be Bearer {token}",
			})
			c.Abort()
			return
		}

		// 解析 access token
		claims, err := utils.ParseAccessToken(parts[1])
		if err != nil {
			// 如果access token无效，检查是否有refresh token
			refreshToken := c.GetHeader("X-Refresh-Token")
			if refreshToken != "" {
				// 尝试使用refresh token获取新的token对
				tokenPair, refreshErr := utils.RefreshTokens(refreshToken)
				if refreshErr == nil {
					// 将新的token对返回给客户端
					c.Header("X-New-Access-Token", tokenPair.AccessToken)
					c.Header("X-New-Refresh-Token", tokenPair.RefreshToken)

					// 使用新的access token的claims
					claims, err = utils.ParseAccessToken(tokenPair.AccessToken)
					if err == nil {
						// 将用户信息存储到上下文中
						c.Set("userCode", claims.UserCode)
						c.Set("username", claims.Username)
						c.Set("roles", claims.Roles)
						c.Next()
						return
					}
				}
			}

			c.JSON(http.StatusUnauthorized, gin.H{
				"code":  401,
				"msg":   "Invalid or expired token",
				"error": err.Error(),
			})
			c.Abort()
			return
		}

		// 将用户信息存储到上下文中
		c.Set("userCode", claims.UserCode)
		c.Set("username", claims.Username)
		c.Set("roles", claims.Roles)

		c.Next()
	}
}

// RefreshTokenHandler 处理token刷新的独立处理器
func RefreshTokenHandler(c *gin.Context) utils.Response {
	refreshToken := c.GetHeader("X-Refresh-Token")
	if refreshToken == "" {
		slog.Error("Refresh token is required")
		return utils.NewErrorResponse(utils.ErrTokenInvalid)
	}

	// 使用refresh token获取新的token对
	tokenPair, err := utils.RefreshTokens(refreshToken)
	if err != nil {
		slog.Error("Invalid or expired refresh token", "error", err)
		return utils.NewErrorResponse(utils.ErrTokenInvalid)
	}
	return utils.NewResponse(utils.StatusOK, tokenPair)
}

// RequireRoles 检查用户是否具有特定角色的中间件
func RequireRoles(requiredRoles ...string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从上下文中获取用户角色
		userRoles, exists := c.Get("roles")
		if !exists {
			c.JSON(http.StatusUnauthorized, gin.H{
				"code": 401,
				"msg":  "User roles not found in context",
			})
			c.Abort()
			return
		}

		// 检查用户是否具有所需角色
		roles := userRoles.([]string)
		hasRequiredRole := false
		for _, requiredRole := range requiredRoles {
			for _, userRole := range roles {
				if requiredRole == userRole {
					hasRequiredRole = true
					break
				}
			}
			if hasRequiredRole {
				break
			}
		}

		if !hasRequiredRole {
			c.JSON(http.StatusForbidden, gin.H{
				"code": 403,
				"msg":  "Insufficient permissions",
			})
			c.Abort()
			return
		}

		c.Next()
	}
}
